| Index: test/cctest/test-debug.cc
|
| diff --git a/test/cctest/test-debug.cc b/test/cctest/test-debug.cc
|
| index 21ba7ddb005cb6a809adc6d9efd3fcb92c00967d..a1547e6d85a80a01cae156ba06174a8fccef9cdd 100644
|
| --- a/test/cctest/test-debug.cc
|
| +++ b/test/cctest/test-debug.cc
|
| @@ -2163,6 +2163,154 @@ TEST(DebugEvaluate) {
|
| CheckDebuggerUnloaded();
|
| }
|
|
|
| +// Copies a C string to a 16-bit string. Does not check for buffer overflow.
|
| +// Does not use the V8 engine to convert strings, so it can be used
|
| +// in any thread. Returns the length of the string.
|
| +int AsciiToUtf16(const char* input_buffer, uint16_t* output_buffer) {
|
| + int i;
|
| + for (i = 0; input_buffer[i] != '\0'; ++i) {
|
| + // ASCII does not use chars > 127, but be careful anyway.
|
| + output_buffer[i] = static_cast<unsigned char>(input_buffer[i]);
|
| + }
|
| + output_buffer[i] = 0;
|
| + return i;
|
| +}
|
| +
|
| +// Copies a 16-bit string to a C string by dropping the high byte of
|
| +// each character. Does not check for buffer overflow.
|
| +// Can be used in any thread. Requires string length as an input.
|
| +int Utf16ToAscii(const uint16_t* input_buffer, int length,
|
| + char* output_buffer, int output_len = -1) {
|
| + if (output_len >= 0) {
|
| + if (length > output_len - 1) {
|
| + length = output_len - 1;
|
| + }
|
| + }
|
| +
|
| + for (int i = 0; i < length; ++i) {
|
| + output_buffer[i] = static_cast<char>(input_buffer[i]);
|
| + }
|
| + output_buffer[length] = '\0';
|
| + return length;
|
| +}
|
| +
|
| +
|
| +// We match parts of the message to get evaluate result int value.
|
| +bool GetEvaluateStringResult(char *message, char* buffer, int buffer_size) {
|
| + const char* value = "\"value\":";
|
| + char* pos = strstr(message, value);
|
| + if (pos == NULL) {
|
| + return false;
|
| + }
|
| + strncpy(buffer, pos, buffer_size);
|
| + buffer[buffer_size - 1] = '\0';
|
| + return true;
|
| +}
|
| +
|
| +
|
| +struct EvaluateResult {
|
| + static const int kBufferSize = 20;
|
| + char buffer[kBufferSize];
|
| +};
|
| +
|
| +struct DebugProcessDebugMessagesData {
|
| + static const int kArraySize = 5;
|
| + int counter;
|
| + EvaluateResult results[kArraySize];
|
| +
|
| + void reset() {
|
| + counter = 0;
|
| + }
|
| + EvaluateResult* current() {
|
| + return &results[counter % kArraySize];
|
| + }
|
| + void next() {
|
| + counter++;
|
| + }
|
| +};
|
| +
|
| +DebugProcessDebugMessagesData process_debug_messages_data;
|
| +
|
| +static void DebugProcessDebugMessagesHandler(
|
| + const uint16_t* message,
|
| + int length,
|
| + v8::Debug::ClientData* client_data) {
|
| +
|
| + const int kBufferSize = 100000;
|
| + char print_buffer[kBufferSize];
|
| + Utf16ToAscii(message, length, print_buffer, kBufferSize);
|
| +
|
| + EvaluateResult* array_item = process_debug_messages_data.current();
|
| +
|
| + bool res = GetEvaluateStringResult(print_buffer,
|
| + array_item->buffer,
|
| + EvaluateResult::kBufferSize);
|
| + if (res) {
|
| + process_debug_messages_data.next();
|
| + }
|
| +}
|
| +
|
| +// Test that the evaluation of expressions works even from ProcessDebugMessages
|
| +// i.e. with empty stack.
|
| +TEST(DebugEvaluateWithoutStack) {
|
| + v8::Debug::SetMessageHandler(DebugProcessDebugMessagesHandler);
|
| +
|
| + v8::HandleScope scope;
|
| + DebugLocalContext env;
|
| +
|
| + const char* source =
|
| + "var v1 = 'Pinguin';\n function getAnimal() { return 'Capy' + 'bara'; }";
|
| +
|
| + v8::Script::Compile(v8::String::New(source))->Run();
|
| +
|
| + v8::Debug::ProcessDebugMessages();
|
| +
|
| + const int kBufferSize = 1000;
|
| + uint16_t buffer[kBufferSize];
|
| +
|
| + const char* command_111 = "{\"seq\":111,"
|
| + "\"type\":\"request\","
|
| + "\"command\":\"evaluate\","
|
| + "\"arguments\":{"
|
| + " \"global\":true,"
|
| + " \"expression\":\"v1\",\"disable_break\":true"
|
| + "}}";
|
| +
|
| + v8::Debug::SendCommand(buffer, AsciiToUtf16(command_111, buffer));
|
| +
|
| + const char* command_112 = "{\"seq\":112,"
|
| + "\"type\":\"request\","
|
| + "\"command\":\"evaluate\","
|
| + "\"arguments\":{"
|
| + " \"global\":true,"
|
| + " \"expression\":\"getAnimal()\",\"disable_break\":true"
|
| + "}}";
|
| +
|
| + v8::Debug::SendCommand(buffer, AsciiToUtf16(command_112, buffer));
|
| +
|
| + const char* command_113 = "{\"seq\":113,"
|
| + "\"type\":\"request\","
|
| + "\"command\":\"evaluate\","
|
| + "\"arguments\":{"
|
| + " \"global\":true,"
|
| + " \"expression\":\"239 + 566\",\"disable_break\":true"
|
| + "}}";
|
| +
|
| + v8::Debug::SendCommand(buffer, AsciiToUtf16(command_113, buffer));
|
| +
|
| + v8::Debug::ProcessDebugMessages();
|
| +
|
| + CHECK_EQ(3, process_debug_messages_data.counter);
|
| +
|
| + CHECK(strcmp("Pinguin", process_debug_messages_data.results[0].buffer));
|
| + CHECK(strcmp("Captbara", process_debug_messages_data.results[1].buffer));
|
| + CHECK(strcmp("805", process_debug_messages_data.results[2].buffer));
|
| +
|
| + v8::Debug::SetMessageHandler(NULL);
|
| + v8::Debug::SetDebugEventListener(NULL);
|
| + CheckDebuggerUnloaded();
|
| +}
|
| +
|
|
|
| // Simple test of the stepping mechanism using only store ICs.
|
| TEST(DebugStepLinear) {
|
| @@ -3593,31 +3741,6 @@ TEST(NoHiddenProperties) {
|
|
|
| // Support classes
|
|
|
| -// Copies a C string to a 16-bit string. Does not check for buffer overflow.
|
| -// Does not use the V8 engine to convert strings, so it can be used
|
| -// in any thread. Returns the length of the string.
|
| -int AsciiToUtf16(const char* input_buffer, uint16_t* output_buffer) {
|
| - int i;
|
| - for (i = 0; input_buffer[i] != '\0'; ++i) {
|
| - // ASCII does not use chars > 127, but be careful anyway.
|
| - output_buffer[i] = static_cast<unsigned char>(input_buffer[i]);
|
| - }
|
| - output_buffer[i] = 0;
|
| - return i;
|
| -}
|
| -
|
| -// Copies a 16-bit string to a C string by dropping the high byte of
|
| -// each character. Does not check for buffer overflow.
|
| -// Can be used in any thread. Requires string length as an input.
|
| -int Utf16ToAscii(const uint16_t* input_buffer, int length,
|
| - char* output_buffer) {
|
| - for (int i = 0; i < length; ++i) {
|
| - output_buffer[i] = static_cast<char>(input_buffer[i]);
|
| - }
|
| - output_buffer[length] = '\0';
|
| - return length;
|
| -}
|
| -
|
| // Provides synchronization between k threads, where k is an input to the
|
| // constructor. The Wait() call blocks a thread until it is called for the
|
| // k'th time, then all calls return. Each ThreadBarrier object can only
|
|
|