|  | 
| 36 | 36 | 
 | 
| 37 | 37 | #include <unordered_set> | 
| 38 | 38 | #include <vector> | 
|  | 39 | +// The C++ style guide recommends using <re2> instead of <regex>. However, the | 
|  | 40 | +// former isn't available in V8. | 
|  | 41 | +#include <regex>  // NOLINT(build/c++11) | 
| 39 | 42 | #include "src/api.h" | 
| 40 | 43 | #include "src/log-utils.h" | 
| 41 | 44 | #include "src/log.h" | 
| @@ -257,30 +260,41 @@ class TestCodeEventHandler : public v8::CodeEventHandler { | 
| 257 | 260 |   explicit TestCodeEventHandler(v8::Isolate* isolate) | 
| 258 | 261 |       : v8::CodeEventHandler(isolate) {} | 
| 259 | 262 | 
 | 
| 260 |  | -  const char* FindLine(const char* prefix, const char* suffix = nullptr, | 
| 261 |  | -                       const char* start = nullptr) { | 
| 262 |  | -    if (!log_.length()) return NULL; | 
| 263 |  | -    const char* c_log = log_.c_str(); | 
| 264 |  | -    if (start == nullptr) start = c_log; | 
| 265 |  | -    const char* end = c_log + log_.length(); | 
| 266 |  | -    return FindLogLine(start, end, prefix, suffix); | 
|  | 263 | +  size_t CountLines(std::string prefix, std::string suffix = std::string()) { | 
|  | 264 | +    if (!log_.length()) return 0; | 
|  | 265 | + | 
|  | 266 | +    std::regex expression("(^|\\n)" + prefix + ".*" + suffix + "(?=\\n|$)"); | 
|  | 267 | + | 
|  | 268 | +    size_t match_count(std::distance( | 
|  | 269 | +        std::sregex_iterator(log_.begin(), log_.end(), expression), | 
|  | 270 | +        std::sregex_iterator())); | 
|  | 271 | + | 
|  | 272 | +    return match_count; | 
| 267 | 273 |   } | 
| 268 | 274 | 
 | 
| 269 | 275 |   void Handle(v8::CodeEvent* code_event) override { | 
| 270 |  | -    const char* code_type = | 
| 271 |  | -        v8::CodeEvent::GetCodeEventTypeName(code_event->GetCodeType()); | 
| 272 |  | -    char function_name[1000]; | 
| 273 |  | -    strncpy(function_name, code_type, 1000); | 
| 274 |  | -    function_name[strlen(code_type)] = ' '; | 
| 275 |  | -    code_event->GetFunctionName()->WriteUtf8( | 
| 276 |  | -        function_name + strlen(code_type) + 1, 1000); | 
| 277 |  | -    function_name[strlen(function_name) + 1] = '\0'; | 
| 278 |  | -    function_name[strlen(function_name)] = '\n'; | 
| 279 |  | - | 
| 280 |  | -    log_ += std::string(function_name); | 
|  | 276 | +    std::string log_line = ""; | 
|  | 277 | +    log_line += v8::CodeEvent::GetCodeEventTypeName(code_event->GetCodeType()); | 
|  | 278 | +    log_line += " "; | 
|  | 279 | +    log_line += FormatName(code_event); | 
|  | 280 | +    log_line += "\n"; | 
|  | 281 | +    log_ += log_line; | 
| 281 | 282 |   } | 
| 282 | 283 | 
 | 
| 283 | 284 |  private: | 
|  | 285 | +  std::string FormatName(v8::CodeEvent* code_event) { | 
|  | 286 | +    std::string name = std::string(code_event->GetComment()); | 
|  | 287 | +    if (name.empty()) { | 
|  | 288 | +      v8::Local<v8::String> functionName = code_event->GetFunctionName(); | 
|  | 289 | +      std::string buffer(functionName->Utf8Length() + 1, 0); | 
|  | 290 | +      functionName->WriteUtf8(&buffer[0], functionName->Utf8Length() + 1); | 
|  | 291 | +      // Sanitize name, removing unwanted \0 resulted from WriteUtf8 | 
|  | 292 | +      name = std::string(buffer.c_str()); | 
|  | 293 | +    } | 
|  | 294 | + | 
|  | 295 | +    return name; | 
|  | 296 | +  } | 
|  | 297 | + | 
| 284 | 298 |   std::string log_; | 
| 285 | 299 | }; | 
| 286 | 300 | 
 | 
| @@ -854,21 +868,24 @@ TEST(ExternalCodeEventListener) { | 
| 854 | 868 |         "testCodeEventListenerBeforeStart('1', 1);"; | 
| 855 | 869 |     CompileRun(source_text_before_start); | 
| 856 | 870 | 
 | 
| 857 |  | -    CHECK_NULL(code_event_handler.FindLine("LazyCompile", | 
| 858 |  | -                                           "testCodeEventListenerBeforeStart")); | 
|  | 871 | +    CHECK_EQ(code_event_handler.CountLines("LazyCompile", | 
|  | 872 | +                                           "testCodeEventListenerBeforeStart"), | 
|  | 873 | +             0); | 
| 859 | 874 | 
 | 
| 860 | 875 |     code_event_handler.Enable(); | 
| 861 | 876 | 
 | 
| 862 |  | -    CHECK_NOT_NULL(code_event_handler.FindLine( | 
| 863 |  | -        "LazyCompile", "testCodeEventListenerBeforeStart")); | 
|  | 877 | +    CHECK_GE(code_event_handler.CountLines("LazyCompile", | 
|  | 878 | +                                           "testCodeEventListenerBeforeStart"), | 
|  | 879 | +             1); | 
| 864 | 880 | 
 | 
| 865 | 881 |     const char* source_text_after_start = | 
| 866 | 882 |         "function testCodeEventListenerAfterStart(a,b) { return a + b };" | 
| 867 | 883 |         "testCodeEventListenerAfterStart('1', 1);"; | 
| 868 | 884 |     CompileRun(source_text_after_start); | 
| 869 | 885 | 
 | 
| 870 |  | -    CHECK_NOT_NULL(code_event_handler.FindLine( | 
| 871 |  | -        "LazyCompile", "testCodeEventListenerAfterStart")); | 
|  | 886 | +    CHECK_GE(code_event_handler.CountLines("LazyCompile", | 
|  | 887 | +                                           "testCodeEventListenerAfterStart"), | 
|  | 888 | +             1); | 
| 872 | 889 | 
 | 
| 873 | 890 |     context->Exit(); | 
| 874 | 891 |   } | 
| @@ -897,21 +914,28 @@ TEST(ExternalCodeEventListenerWithInterpretedFramesNativeStack) { | 
| 897 | 914 |         "testCodeEventListenerBeforeStart('1', 1);"; | 
| 898 | 915 |     CompileRun(source_text_before_start); | 
| 899 | 916 | 
 | 
| 900 |  | -    CHECK_NULL(code_event_handler.FindLine("InterpretedFunction", | 
| 901 |  | -                                           "testCodeEventListenerBeforeStart")); | 
|  | 917 | +    CHECK_EQ(code_event_handler.CountLines("InterpretedFunction", | 
|  | 918 | +                                           "testCodeEventListenerBeforeStart"), | 
|  | 919 | +             0); | 
| 902 | 920 | 
 | 
| 903 | 921 |     code_event_handler.Enable(); | 
| 904 | 922 | 
 | 
| 905 |  | -    CHECK_NOT_NULL(code_event_handler.FindLine( | 
| 906 |  | -        "InterpretedFunction", "testCodeEventListenerBeforeStart")); | 
|  | 923 | +    CHECK_GE(code_event_handler.CountLines("InterpretedFunction", | 
|  | 924 | +                                           "testCodeEventListenerBeforeStart"), | 
|  | 925 | +             1); | 
| 907 | 926 | 
 | 
| 908 | 927 |     const char* source_text_after_start = | 
| 909 | 928 |         "function testCodeEventListenerAfterStart(a,b) { return a + b };" | 
| 910 | 929 |         "testCodeEventListenerAfterStart('1', 1);"; | 
| 911 | 930 |     CompileRun(source_text_after_start); | 
| 912 | 931 | 
 | 
| 913 |  | -    CHECK_NOT_NULL(code_event_handler.FindLine( | 
| 914 |  | -        "InterpretedFunction", "testCodeEventListenerAfterStart")); | 
|  | 932 | +    CHECK_GE(code_event_handler.CountLines("InterpretedFunction", | 
|  | 933 | +                                           "testCodeEventListenerAfterStart"), | 
|  | 934 | +             1); | 
|  | 935 | + | 
|  | 936 | +    CHECK_EQ( | 
|  | 937 | +        code_event_handler.CountLines("Builtin", "InterpreterEntryTrampoline"), | 
|  | 938 | +        1); | 
| 915 | 939 | 
 | 
| 916 | 940 |     context->Exit(); | 
| 917 | 941 |   } | 
|  | 
0 commit comments