| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 5770 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5781 // handler. | 5781 // handler. |
| 5782 CompileRun("throw 1"); | 5782 CompileRun("throw 1"); |
| 5783 | 5783 |
| 5784 // The message handler should be called. | 5784 // The message handler should be called. |
| 5785 CHECK_EQ(1, message_handler_hit_count); | 5785 CHECK_EQ(1, message_handler_hit_count); |
| 5786 | 5786 |
| 5787 CheckDebuggerUnloaded(true); | 5787 CheckDebuggerUnloaded(true); |
| 5788 } | 5788 } |
| 5789 | 5789 |
| 5790 | 5790 |
| 5791 /* Test DebugMessageDispatch */ | |
| 5792 /* In this test, the V8 thread waits for a message from the debug thread. | |
| 5793 * The DebugMessageDispatchHandler is executed from the debugger thread | |
| 5794 * which signals the V8 thread to wake up. | |
| 5795 */ | |
| 5796 | |
| 5797 class DebugMessageDispatchV8Thread : public v8::internal::Thread { | |
| 5798 public: | |
| 5799 DebugMessageDispatchV8Thread() : Thread("DebugMessageDispatchV8Thread") { } | |
| 5800 void Run(); | |
| 5801 }; | |
| 5802 | |
| 5803 class DebugMessageDispatchDebuggerThread : public v8::internal::Thread { | |
| 5804 public: | |
| 5805 DebugMessageDispatchDebuggerThread() | |
| 5806 : Thread("DebugMessageDispatchDebuggerThread") { } | |
| 5807 void Run(); | |
| 5808 }; | |
| 5809 | |
| 5810 Barriers* debug_message_dispatch_barriers; | |
| 5811 | |
| 5812 | |
| 5813 static void DebugMessageHandler() { | |
| 5814 debug_message_dispatch_barriers->semaphore_1.Signal(); | |
| 5815 } | |
| 5816 | |
| 5817 | |
| 5818 void DebugMessageDispatchV8Thread::Run() { | |
| 5819 v8::Isolate::Scope isolate_scope(CcTest::isolate()); | |
| 5820 DebugLocalContext env; | |
| 5821 v8::HandleScope scope(env->GetIsolate()); | |
| 5822 | |
| 5823 // Set up debug message dispatch handler. | |
| 5824 v8::Debug::SetDebugMessageDispatchHandler(DebugMessageHandler); | |
| 5825 | |
| 5826 CompileRun("var y = 1 + 2;\n"); | |
| 5827 debug_message_dispatch_barriers->barrier_1.Wait(); | |
| 5828 debug_message_dispatch_barriers->semaphore_1.Wait(); | |
| 5829 debug_message_dispatch_barriers->barrier_2.Wait(); | |
| 5830 } | |
| 5831 | |
| 5832 | |
| 5833 void DebugMessageDispatchDebuggerThread::Run() { | |
| 5834 debug_message_dispatch_barriers->barrier_1.Wait(); | |
| 5835 SendContinueCommand(); | |
| 5836 debug_message_dispatch_barriers->barrier_2.Wait(); | |
| 5837 } | |
| 5838 | |
| 5839 | |
| 5840 TEST(DebuggerDebugMessageDispatch) { | |
| 5841 DebugMessageDispatchDebuggerThread debug_message_dispatch_debugger_thread; | |
| 5842 DebugMessageDispatchV8Thread debug_message_dispatch_v8_thread; | |
| 5843 | |
| 5844 // Create a V8 environment | |
| 5845 Barriers stack_allocated_debug_message_dispatch_barriers; | |
| 5846 debug_message_dispatch_barriers = | |
| 5847 &stack_allocated_debug_message_dispatch_barriers; | |
| 5848 | |
| 5849 debug_message_dispatch_v8_thread.Start(); | |
| 5850 debug_message_dispatch_debugger_thread.Start(); | |
| 5851 | |
| 5852 debug_message_dispatch_v8_thread.Join(); | |
| 5853 debug_message_dispatch_debugger_thread.Join(); | |
| 5854 } | |
| 5855 | |
| 5856 | |
| 5857 TEST(DebuggerAgent) { | |
| 5858 v8::V8::Initialize(); | |
| 5859 i::Debugger* debugger = CcTest::i_isolate()->debugger(); | |
| 5860 // Make sure these ports is not used by other tests to allow tests to run in | |
| 5861 // parallel. | |
| 5862 const int kPort1 = 5858 + FlagDependentPortOffset(); | |
| 5863 const int kPort2 = 5857 + FlagDependentPortOffset(); | |
| 5864 const int kPort3 = 5856 + FlagDependentPortOffset(); | |
| 5865 | |
| 5866 // Make a string with the port2 number. | |
| 5867 const int kPortBufferLen = 6; | |
| 5868 char port2_str[kPortBufferLen]; | |
| 5869 OS::SNPrintF(i::Vector<char>(port2_str, kPortBufferLen), "%d", kPort2); | |
| 5870 | |
| 5871 bool ok; | |
| 5872 | |
| 5873 // Test starting and stopping the agent without any client connection. | |
| 5874 debugger->StartAgent("test", kPort1); | |
| 5875 debugger->StopAgent(); | |
| 5876 // Test starting the agent, connecting a client and shutting down the agent | |
| 5877 // with the client connected. | |
| 5878 ok = debugger->StartAgent("test", kPort2); | |
| 5879 CHECK(ok); | |
| 5880 debugger->WaitForAgent(); | |
| 5881 i::Socket* client = new i::Socket; | |
| 5882 ok = client->Connect("localhost", port2_str); | |
| 5883 CHECK(ok); | |
| 5884 // It is important to wait for a message from the agent. Otherwise, | |
| 5885 // we can close the server socket during "accept" syscall, making it failing | |
| 5886 // (at least on Linux), and the test will work incorrectly. | |
| 5887 char buf; | |
| 5888 ok = client->Receive(&buf, 1) == 1; | |
| 5889 CHECK(ok); | |
| 5890 debugger->StopAgent(); | |
| 5891 delete client; | |
| 5892 | |
| 5893 // Test starting and stopping the agent with the required port already | |
| 5894 // occoupied. | |
| 5895 i::Socket* server = new i::Socket; | |
| 5896 ok = server->Bind(kPort3); | |
| 5897 CHECK(ok); | |
| 5898 | |
| 5899 debugger->StartAgent("test", kPort3); | |
| 5900 debugger->StopAgent(); | |
| 5901 | |
| 5902 delete server; | |
| 5903 } | |
| 5904 | |
| 5905 | |
| 5906 class DebuggerAgentProtocolServerThread : public i::Thread { | |
| 5907 public: | |
| 5908 explicit DebuggerAgentProtocolServerThread(int port) | |
| 5909 : Thread("DebuggerAgentProtocolServerThread"), | |
| 5910 port_(port), | |
| 5911 server_(NULL), | |
| 5912 client_(NULL), | |
| 5913 listening_(0) { | |
| 5914 } | |
| 5915 ~DebuggerAgentProtocolServerThread() { | |
| 5916 // Close both sockets. | |
| 5917 delete client_; | |
| 5918 delete server_; | |
| 5919 } | |
| 5920 | |
| 5921 void Run(); | |
| 5922 void WaitForListening() { listening_.Wait(); } | |
| 5923 char* body() { return body_.get(); } | |
| 5924 | |
| 5925 private: | |
| 5926 int port_; | |
| 5927 i::SmartArrayPointer<char> body_; | |
| 5928 i::Socket* server_; // Server socket used for bind/accept. | |
| 5929 i::Socket* client_; // Single client connection used by the test. | |
| 5930 i::Semaphore listening_; // Signalled when the server is in listen mode. | |
| 5931 }; | |
| 5932 | |
| 5933 | |
| 5934 void DebuggerAgentProtocolServerThread::Run() { | |
| 5935 bool ok; | |
| 5936 | |
| 5937 // Create the server socket and bind it to the requested port. | |
| 5938 server_ = new i::Socket; | |
| 5939 CHECK(server_ != NULL); | |
| 5940 ok = server_->Bind(port_); | |
| 5941 CHECK(ok); | |
| 5942 | |
| 5943 // Listen for new connections. | |
| 5944 ok = server_->Listen(1); | |
| 5945 CHECK(ok); | |
| 5946 listening_.Signal(); | |
| 5947 | |
| 5948 // Accept a connection. | |
| 5949 client_ = server_->Accept(); | |
| 5950 CHECK(client_ != NULL); | |
| 5951 | |
| 5952 // Receive a debugger agent protocol message. | |
| 5953 i::DebuggerAgentUtil::ReceiveMessage(client_); | |
| 5954 } | |
| 5955 | |
| 5956 | |
| 5957 TEST(DebuggerAgentProtocolOverflowHeader) { | |
| 5958 // Make sure this port is not used by other tests to allow tests to run in | |
| 5959 // parallel. | |
| 5960 const int kPort = 5860 + FlagDependentPortOffset(); | |
| 5961 static const char* kLocalhost = "localhost"; | |
| 5962 | |
| 5963 // Make a string with the port number. | |
| 5964 const int kPortBufferLen = 6; | |
| 5965 char port_str[kPortBufferLen]; | |
| 5966 OS::SNPrintF(i::Vector<char>(port_str, kPortBufferLen), "%d", kPort); | |
| 5967 | |
| 5968 // Create a socket server to receive a debugger agent message. | |
| 5969 DebuggerAgentProtocolServerThread* server = | |
| 5970 new DebuggerAgentProtocolServerThread(kPort); | |
| 5971 server->Start(); | |
| 5972 server->WaitForListening(); | |
| 5973 | |
| 5974 // Connect. | |
| 5975 i::Socket* client = new i::Socket; | |
| 5976 CHECK(client != NULL); | |
| 5977 bool ok = client->Connect(kLocalhost, port_str); | |
| 5978 CHECK(ok); | |
| 5979 | |
| 5980 // Send headers which overflow the receive buffer. | |
| 5981 static const int kBufferSize = 1000; | |
| 5982 char buffer[kBufferSize]; | |
| 5983 | |
| 5984 // Long key and short value: XXXX....XXXX:0\r\n. | |
| 5985 for (int i = 0; i < kBufferSize - 4; i++) { | |
| 5986 buffer[i] = 'X'; | |
| 5987 } | |
| 5988 buffer[kBufferSize - 4] = ':'; | |
| 5989 buffer[kBufferSize - 3] = '0'; | |
| 5990 buffer[kBufferSize - 2] = '\r'; | |
| 5991 buffer[kBufferSize - 1] = '\n'; | |
| 5992 int result = client->Send(buffer, kBufferSize); | |
| 5993 CHECK_EQ(kBufferSize, result); | |
| 5994 | |
| 5995 // Short key and long value: X:XXXX....XXXX\r\n. | |
| 5996 buffer[0] = 'X'; | |
| 5997 buffer[1] = ':'; | |
| 5998 for (int i = 2; i < kBufferSize - 2; i++) { | |
| 5999 buffer[i] = 'X'; | |
| 6000 } | |
| 6001 buffer[kBufferSize - 2] = '\r'; | |
| 6002 buffer[kBufferSize - 1] = '\n'; | |
| 6003 result = client->Send(buffer, kBufferSize); | |
| 6004 CHECK_EQ(kBufferSize, result); | |
| 6005 | |
| 6006 // Add empty body to request. | |
| 6007 const char* content_length_zero_header = "Content-Length:0\r\n"; | |
| 6008 int length = StrLength(content_length_zero_header); | |
| 6009 result = client->Send(content_length_zero_header, length); | |
| 6010 CHECK_EQ(length, result); | |
| 6011 result = client->Send("\r\n", 2); | |
| 6012 CHECK_EQ(2, result); | |
| 6013 | |
| 6014 // Wait until data is received. | |
| 6015 server->Join(); | |
| 6016 | |
| 6017 // Check for empty body. | |
| 6018 CHECK(server->body() == NULL); | |
| 6019 | |
| 6020 // Close the client before the server to avoid TIME_WAIT issues. | |
| 6021 client->Shutdown(); | |
| 6022 delete client; | |
| 6023 delete server; | |
| 6024 } | |
| 6025 | |
| 6026 | |
| 6027 // Test for issue http://code.google.com/p/v8/issues/detail?id=289. | 5791 // Test for issue http://code.google.com/p/v8/issues/detail?id=289. |
| 6028 // Make sure that DebugGetLoadedScripts doesn't return scripts | 5792 // Make sure that DebugGetLoadedScripts doesn't return scripts |
| 6029 // with disposed external source. | 5793 // with disposed external source. |
| 6030 class EmptyExternalStringResource : public v8::String::ExternalStringResource { | 5794 class EmptyExternalStringResource : public v8::String::ExternalStringResource { |
| 6031 public: | 5795 public: |
| 6032 EmptyExternalStringResource() { empty_[0] = 0; } | 5796 EmptyExternalStringResource() { empty_[0] = 0; } |
| 6033 virtual ~EmptyExternalStringResource() {} | 5797 virtual ~EmptyExternalStringResource() {} |
| 6034 virtual size_t length() const { return empty_.length(); } | 5798 virtual size_t length() const { return empty_.length(); } |
| 6035 virtual const uint16_t* data() const { return empty_.start(); } | 5799 virtual const uint16_t* data() const { return empty_.start(); } |
| 6036 private: | 5800 private: |
| (...skipping 739 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6776 | 6540 |
| 6777 // Get rid of the debug message handler. | 6541 // Get rid of the debug message handler. |
| 6778 v8::Debug::SetMessageHandler2(NULL); | 6542 v8::Debug::SetMessageHandler2(NULL); |
| 6779 CheckDebuggerUnloaded(); | 6543 CheckDebuggerUnloaded(); |
| 6780 } | 6544 } |
| 6781 | 6545 |
| 6782 | 6546 |
| 6783 static int counting_message_handler_counter; | 6547 static int counting_message_handler_counter; |
| 6784 | 6548 |
| 6785 static void CountingMessageHandler(const v8::Debug::Message& message) { | 6549 static void CountingMessageHandler(const v8::Debug::Message& message) { |
| 6786 counting_message_handler_counter++; | 6550 if (message.IsResponse()) counting_message_handler_counter++; |
| 6787 } | 6551 } |
| 6788 | 6552 |
| 6789 | 6553 |
| 6790 // Test that debug messages get processed when ProcessDebugMessages is called. | 6554 // Test that debug messages get processed when ProcessDebugMessages is called. |
| 6791 TEST(ProcessDebugMessages) { | 6555 TEST(ProcessDebugMessages) { |
| 6792 DebugLocalContext env; | 6556 DebugLocalContext env; |
| 6793 v8::Isolate* isolate = env->GetIsolate(); | 6557 v8::Isolate* isolate = env->GetIsolate(); |
| 6794 v8::HandleScope scope(isolate); | 6558 v8::HandleScope scope(isolate); |
| 6795 | 6559 |
| 6796 counting_message_handler_counter = 0; | 6560 counting_message_handler_counter = 0; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 6823 v8::Debug::ProcessDebugMessages(); | 6587 v8::Debug::ProcessDebugMessages(); |
| 6824 // At least two messages should come | 6588 // At least two messages should come |
| 6825 CHECK_GE(counting_message_handler_counter, 2); | 6589 CHECK_GE(counting_message_handler_counter, 2); |
| 6826 | 6590 |
| 6827 // Get rid of the debug message handler. | 6591 // Get rid of the debug message handler. |
| 6828 v8::Debug::SetMessageHandler2(NULL); | 6592 v8::Debug::SetMessageHandler2(NULL); |
| 6829 CheckDebuggerUnloaded(); | 6593 CheckDebuggerUnloaded(); |
| 6830 } | 6594 } |
| 6831 | 6595 |
| 6832 | 6596 |
| 6597 class SendCommandThread : public v8::internal::Thread { |
| 6598 public: |
| 6599 explicit SendCommandThread(v8::Isolate* isolate) |
| 6600 : Thread("SendCommandThread"), |
| 6601 semaphore_(0), |
| 6602 isolate_(isolate) { } |
| 6603 |
| 6604 static void ProcessDebugMessages(v8::Isolate* isolate, void* data) { |
| 6605 v8::Debug::ProcessDebugMessages(); |
| 6606 reinterpret_cast<v8::internal::Semaphore*>(data)->Signal(); |
| 6607 } |
| 6608 |
| 6609 virtual void Run() { |
| 6610 semaphore_.Wait(); |
| 6611 const int kBufferSize = 1000; |
| 6612 uint16_t buffer[kBufferSize]; |
| 6613 const char* scripts_command = |
| 6614 "{\"seq\":0," |
| 6615 "\"type\":\"request\"," |
| 6616 "\"command\":\"scripts\"}"; |
| 6617 int length = AsciiToUtf16(scripts_command, buffer); |
| 6618 // Send scripts command. |
| 6619 |
| 6620 for (int i = 0; i < 100; i++) { |
| 6621 CHECK_EQ(i, counting_message_handler_counter); |
| 6622 // Queue debug message. |
| 6623 v8::Debug::SendCommand(isolate_, buffer, length); |
| 6624 // Synchronize with the main thread to force message processing. |
| 6625 isolate_->RequestInterrupt(ProcessDebugMessages, &semaphore_); |
| 6626 semaphore_.Wait(); |
| 6627 } |
| 6628 |
| 6629 v8::V8::TerminateExecution(isolate_); |
| 6630 } |
| 6631 |
| 6632 void StartSending() { |
| 6633 semaphore_.Signal(); |
| 6634 } |
| 6635 |
| 6636 private: |
| 6637 v8::internal::Semaphore semaphore_; |
| 6638 v8::Isolate* isolate_; |
| 6639 }; |
| 6640 |
| 6641 |
| 6642 static SendCommandThread* send_command_thread_ = NULL; |
| 6643 |
| 6644 static void StartSendingCommands( |
| 6645 const v8::FunctionCallbackInfo<v8::Value>& info) { |
| 6646 send_command_thread_->StartSending(); |
| 6647 } |
| 6648 |
| 6649 |
| 6650 TEST(ProcessDebugMessagesThreaded) { |
| 6651 DebugLocalContext env; |
| 6652 v8::Isolate* isolate = env->GetIsolate(); |
| 6653 v8::HandleScope scope(isolate); |
| 6654 |
| 6655 counting_message_handler_counter = 0; |
| 6656 |
| 6657 v8::Debug::SetMessageHandler2(CountingMessageHandler); |
| 6658 send_command_thread_ = new SendCommandThread(isolate); |
| 6659 send_command_thread_->Start(); |
| 6660 |
| 6661 v8::Handle<v8::FunctionTemplate> start = |
| 6662 v8::FunctionTemplate::New(isolate, StartSendingCommands); |
| 6663 env->Global()->Set(v8_str("start"), start->GetFunction()); |
| 6664 |
| 6665 CompileRun("start(); while (true) { }"); |
| 6666 |
| 6667 CHECK_EQ(100, counting_message_handler_counter); |
| 6668 |
| 6669 v8::Debug::SetMessageHandler2(NULL); |
| 6670 CheckDebuggerUnloaded(); |
| 6671 } |
| 6672 |
| 6673 |
| 6833 struct BacktraceData { | 6674 struct BacktraceData { |
| 6834 static int frame_counter; | 6675 static int frame_counter; |
| 6835 static void MessageHandler(const v8::Debug::Message& message) { | 6676 static void MessageHandler(const v8::Debug::Message& message) { |
| 6836 char print_buffer[1000]; | 6677 char print_buffer[1000]; |
| 6837 v8::String::Value json(message.GetJSON()); | 6678 v8::String::Value json(message.GetJSON()); |
| 6838 Utf16ToAscii(*json, json.length(), print_buffer, 1000); | 6679 Utf16ToAscii(*json, json.length(), print_buffer, 1000); |
| 6839 | 6680 |
| 6840 if (strstr(print_buffer, "backtrace") == NULL) { | 6681 if (strstr(print_buffer, "backtrace") == NULL) { |
| 6841 return; | 6682 return; |
| 6842 } | 6683 } |
| (...skipping 738 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 7581 env->Global()->Set(v8_str("add_debug_break"), add_debug_break); | 7422 env->Global()->Set(v8_str("add_debug_break"), add_debug_break); |
| 7582 | 7423 |
| 7583 CompileRun("(function loop() {" | 7424 CompileRun("(function loop() {" |
| 7584 " for (var j = 0; j < 1000; j++) {" | 7425 " for (var j = 0; j < 1000; j++) {" |
| 7585 " for (var i = 0; i < 1000; i++) {" | 7426 " for (var i = 0; i < 1000; i++) {" |
| 7586 " if (i == 999) add_debug_break();" | 7427 " if (i == 999) add_debug_break();" |
| 7587 " }" | 7428 " }" |
| 7588 " }" | 7429 " }" |
| 7589 "})()"); | 7430 "})()"); |
| 7590 } | 7431 } |
| OLD | NEW |