Index: test/cctest/test-heap-profiler.cc |
diff --git a/test/cctest/test-heap-profiler.cc b/test/cctest/test-heap-profiler.cc |
index a2fd09e9f59d4edd27b4c6ca1c0b3800648e8729..45976cf7702dd7ef797feed12ef7480acf23d05a 100644 |
--- a/test/cctest/test-heap-profiler.cc |
+++ b/test/cctest/test-heap-profiler.cc |
@@ -845,6 +845,19 @@ TEST(HeapSnapshotRootPreservedAfterSorting) { |
namespace { |
+class OneByteResource : public v8::String::ExternalOneByteStringResource { |
+ public: |
+ explicit OneByteResource(i::Vector<char> string) : data_(string.start()) { |
+ length_ = string.length(); |
+ } |
+ virtual const char* data() const { return data_; } |
+ virtual size_t length() const { return length_; } |
+ |
+ private: |
+ const char* data_; |
+ size_t length_; |
+}; |
+ |
class TestJSONStream : public v8::OutputStream { |
public: |
TestJSONStream() : eos_signaled_(0), abort_countdown_(-1) {} |
@@ -868,24 +881,38 @@ class TestJSONStream : public v8::OutputStream { |
int eos_signaled() { return eos_signaled_; } |
int size() { return buffer_.size(); } |
+ // Verifies that the stream contains JSON, parses, and returns the parsed |
+ // result. |
+ v8::Local<v8::Object> verifyAndParseJSON(LocalContext& env) { |
+ i::ScopedVector<char> json(size()); |
+ WriteTo(json); |
+ |
+ // Verify that string is valid JSON. |
+ OneByteResource* json_res = new OneByteResource(json); |
+ v8::Local<v8::String> json_string = |
+ v8::String::NewExternalOneByte(env->GetIsolate(), json_res) |
+ .ToLocalChecked(); |
+ env->Global() |
+ ->Set(env.local(), v8_str("json_snapshot"), json_string) |
+ .FromJust(); |
+ v8::Local<v8::Value> snapshot_parse_result = |
+ CompileRun("var parsed = JSON.parse(json_snapshot); true;"); |
+ CHECK(!snapshot_parse_result.IsEmpty()); |
+ |
+ v8::Local<v8::Object> parsed = env->Global() |
+ ->Get(env.local(), v8_str("parsed")) |
+ .ToLocalChecked() |
+ ->ToObject(env.local()) |
+ .ToLocalChecked(); |
+ return parsed; |
+ } |
+ |
private: |
i::Collector<char> buffer_; |
int eos_signaled_; |
int abort_countdown_; |
}; |
-class OneByteResource : public v8::String::ExternalOneByteStringResource { |
- public: |
- explicit OneByteResource(i::Vector<char> string) : data_(string.start()) { |
- length_ = string.length(); |
- } |
- virtual const char* data() const { return data_; } |
- virtual size_t length() const { return length_; } |
- private: |
- const char* data_; |
- size_t length_; |
-}; |
- |
} // namespace |
TEST(HeapSnapshotJSONSerialization) { |
@@ -908,28 +935,8 @@ TEST(HeapSnapshotJSONSerialization) { |
snapshot->Serialize(&stream, v8::HeapSnapshot::kJSON); |
CHECK_GT(stream.size(), 0); |
CHECK_EQ(1, stream.eos_signaled()); |
- i::ScopedVector<char> json(stream.size()); |
- stream.WriteTo(json); |
- // Verify that snapshot string is valid JSON. |
- OneByteResource* json_res = new OneByteResource(json); |
- v8::Local<v8::String> json_string = |
- v8::String::NewExternalOneByte(env->GetIsolate(), json_res) |
- .ToLocalChecked(); |
- env->Global() |
- ->Set(env.local(), v8_str("json_snapshot"), json_string) |
- .FromJust(); |
- v8::Local<v8::Value> snapshot_parse_result = CompileRun( |
- "var parsed = JSON.parse(json_snapshot); true;"); |
- CHECK(!snapshot_parse_result.IsEmpty()); |
- |
- // Verify that snapshot object has required fields. |
- v8::Local<v8::Object> parsed_snapshot = |
- env->Global() |
- ->Get(env.local(), v8_str("parsed")) |
- .ToLocalChecked() |
- ->ToObject(env.local()) |
- .ToLocalChecked(); |
+ v8::Local<v8::Object> parsed_snapshot = stream.verifyAndParseJSON(env); |
CHECK(parsed_snapshot->Has(env.local(), v8_str("snapshot")).FromJust()); |
CHECK(parsed_snapshot->Has(env.local(), v8_str("nodes")).FromJust()); |
CHECK(parsed_snapshot->Has(env.local(), v8_str("edges")).FromJust()); |
@@ -2852,3 +2859,55 @@ TEST(AddressToTraceMap) { |
CHECK_EQ(0u, map.size()); |
CHECK_EQ(0u, map.GetTraceNodeId(ToAddress(0x400))); |
} |
+ |
+ |
+TEST(SamplingHeapProfiler) { |
+ v8::HandleScope scope(v8::Isolate::GetCurrent()); |
+ LocalContext env; |
+ v8::HeapProfiler* heap_profiler = env->GetIsolate()->GetHeapProfiler(); |
+ |
+ // GetHeapSample should return an empty stream when called before starting |
+ // the sampling heap profiler. |
+ TestJSONStream stream0; |
+ heap_profiler->GetHeapSample(&stream0); |
+ CHECK_EQ(stream0.size(), 0); |
+ CHECK_EQ(1, stream0.eos_signaled()); |
+ |
+ heap_profiler->StartSamplingHeapProfiler(); |
+ CompileRun( |
+ "var A = [];\n" |
+ "function bar(size) { return new Array(size); }\n" |
+ "var foo = function() {\n" |
+ " for (var i = 0; i < 1024; ++i) {\n" |
+ " A[i] = bar(1024);\n" |
+ " }\n" |
+ "}\n" |
+ "foo();"); |
+ |
+ TestJSONStream stream1; |
+ heap_profiler->GetHeapSample(&stream1); |
+ heap_profiler->StopSamplingHeapProfiler(); |
+ |
+ CHECK_GT(stream1.size(), 0); |
+ CHECK_EQ(1, stream1.eos_signaled()); |
+ |
+ v8::Local<v8::Object> sample = stream1.verifyAndParseJSON(env); |
+ CHECK(sample->IsArray()); |
+ v8::Local<v8::Value> validation_result = CompileRun( |
+ "parsed.every(allocation => {\n" |
+ " return allocation.size && Array.isArray(allocation.stack) &&\n" |
+ " allocation.stack.every(frame => {\n" |
+ " return frame.hasOwnProperty('name') &&\n" |
+ " frame.hasOwnProperty('scriptName') &&\n" |
+ " frame.hasOwnProperty('line') &&\n" |
+ " frame.hasOwnProperty('column');\n" |
+ " });\n" |
+ "});"); |
+ CHECK(validation_result->IsTrue()); |
+ |
+ // Samples are reset once sampling heap profiler is stopped. |
+ TestJSONStream stream2; |
+ heap_profiler->GetHeapSample(&stream2); |
+ CHECK_EQ(stream2.size(), 0); |
+ CHECK_EQ(1, stream2.eos_signaled()); |
+} |