PHP WebShell
Текущая директория: /usr/lib/node_modules/bitgo/node_modules/react-native/ReactCommon/jsinspector-modern/tracing/tests
Просмотр файла: RuntimeSamplingProfileTraceEventSerializerTest.cpp
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <jsinspector-modern/tracing/RuntimeSamplingProfileTraceEventSerializer.h>
#include <jsinspector-modern/tracing/Timing.h>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <utility>
namespace facebook::react::jsinspector_modern::tracing {
class RuntimeSamplingProfileTraceEventSerializerTest : public ::testing::Test {
protected:
std::vector<folly::dynamic> notificationEvents_;
std::function<void(const folly::dynamic& traceEventsChunk)>
createNotificationCallback() {
return [this](const folly::dynamic& traceEventsChunk) {
notificationEvents_.push_back(traceEventsChunk);
};
}
RuntimeSamplingProfile::SampleCallStackFrame createJSCallFrame(
std::string_view functionName,
uint32_t scriptId = 1,
std::optional<std::string_view> url = std::nullopt,
std::optional<uint32_t> lineNumber = std::nullopt,
std::optional<uint32_t> columnNumber = std::nullopt) {
return RuntimeSamplingProfile::SampleCallStackFrame(
RuntimeSamplingProfile::SampleCallStackFrame::Kind::JSFunction,
scriptId,
functionName,
url,
lineNumber,
columnNumber);
}
RuntimeSamplingProfile::SampleCallStackFrame createGCCallFrame() {
return RuntimeSamplingProfile::SampleCallStackFrame(
RuntimeSamplingProfile::SampleCallStackFrame::Kind::GarbageCollector,
0,
"(garbage collector)");
}
RuntimeSamplingProfile::Sample createSample(
uint64_t timestamp,
uint64_t threadId,
std::vector<RuntimeSamplingProfile::SampleCallStackFrame> callStack) {
return {timestamp, threadId, std::move(callStack)};
}
RuntimeSamplingProfile createEmptyProfile() {
return {"TestRuntime", {}, {}};
}
RuntimeSamplingProfile createProfileWithSamples(
std::vector<RuntimeSamplingProfile::Sample> samples) {
return {"TestRuntime", std::move(samples), {}};
}
};
TEST_F(RuntimeSamplingProfileTraceEventSerializerTest, EmptyProfile) {
// Setup
auto notificationCallback = createNotificationCallback();
RuntimeSamplingProfileTraceEventSerializer serializer(
PerformanceTracer::getInstance(), notificationCallback, 10);
auto profile = createEmptyProfile();
auto tracingStartTime = HighResTimeStamp::now();
// Execute
serializer.serializeAndNotify(profile, tracingStartTime);
// Nothing should be reported if the profile is empty.
EXPECT_TRUE(notificationEvents_.empty());
}
TEST_F(
RuntimeSamplingProfileTraceEventSerializerTest,
SameCallFramesAreMerged) {
// Setup
auto notificationCallback = createNotificationCallback();
RuntimeSamplingProfileTraceEventSerializer serializer(
PerformanceTracer::getInstance(), notificationCallback, 10);
// [ foo ]
// [ bar ]
// [baz][(gc)]
std::vector<RuntimeSamplingProfile::SampleCallStackFrame> callStack1 = {
createJSCallFrame("bar", 1, "test.js", 20, 10),
createJSCallFrame("foo", 1, "test.js", 10, 5),
};
std::vector<RuntimeSamplingProfile::SampleCallStackFrame> callStack2 = {
createJSCallFrame("baz", 1, "other.js", 5, 1),
createJSCallFrame("bar", 1, "test.js", 20, 10),
createJSCallFrame("foo", 1, "test.js", 10, 5),
};
std::vector<RuntimeSamplingProfile::SampleCallStackFrame> callStack3 = {
createGCCallFrame(),
createJSCallFrame("bar", 1, "test.js", 20, 10),
createJSCallFrame("foo", 1, "test.js", 10, 5),
};
uint64_t threadId = 1;
uint64_t timestamp1 = 1000000;
uint64_t timestamp2 = 2000000;
uint64_t timestamp3 = 3000000;
auto samples = std::vector<RuntimeSamplingProfile::Sample>{};
samples.emplace_back(createSample(timestamp1, threadId, callStack1));
samples.emplace_back(createSample(timestamp2, threadId, callStack2));
samples.emplace_back(createSample(timestamp3, threadId, callStack3));
auto profile = createProfileWithSamples(std::move(samples));
auto tracingStartTime = HighResTimeStamp::now();
// Execute
serializer.serializeAndNotify(profile, tracingStartTime);
// Verify
ASSERT_EQ(notificationEvents_.size(), 2);
// (root), (program), (idle), foo, bar, baz, (garbage collector)
ASSERT_EQ(
notificationEvents_[1][0]["args"]["data"]["cpuProfile"]["nodes"].size(),
7);
}
TEST_F(RuntimeSamplingProfileTraceEventSerializerTest, EmptySample) {
// Setup
auto notificationCallback = createNotificationCallback();
RuntimeSamplingProfileTraceEventSerializer serializer(
PerformanceTracer::getInstance(), notificationCallback, 10);
// Create an empty sample (no call stack)
std::vector<RuntimeSamplingProfile::SampleCallStackFrame> emptyCallStack;
uint64_t threadId = 1;
uint64_t timestamp = 1000000;
auto samples = std::vector<RuntimeSamplingProfile::Sample>{};
samples.emplace_back(createSample(timestamp, threadId, emptyCallStack));
auto profile = createProfileWithSamples(std::move(samples));
auto tracingStartTime = HighResTimeStamp::now();
// Mock the performance tracer methods
folly::dynamic profileEvent = folly::dynamic::object;
folly::dynamic chunkEvent = folly::dynamic::object;
// Execute
serializer.serializeAndNotify(profile, tracingStartTime);
// Verify
// [["Profile"], ["ProfileChunk"]]
ASSERT_EQ(notificationEvents_.size(), 2);
// (root), (program), (idle)
ASSERT_EQ(
notificationEvents_[1][0]["args"]["data"]["cpuProfile"]["nodes"].size(),
3);
}
TEST_F(
RuntimeSamplingProfileTraceEventSerializerTest,
SamplesFromDifferentThreads) {
// Setup
auto notificationCallback = createNotificationCallback();
RuntimeSamplingProfileTraceEventSerializer serializer(
PerformanceTracer::getInstance(), notificationCallback, 10);
// Create samples with different thread IDs
std::vector<RuntimeSamplingProfile::SampleCallStackFrame> callStack = {
createJSCallFrame("foo", 1, "test.js", 10, 5)};
uint64_t timestamp = 1000000;
uint64_t threadId1 = 1;
uint64_t threadId2 = 2;
auto samples = std::vector<RuntimeSamplingProfile::Sample>{};
samples.emplace_back(createSample(timestamp, threadId1, callStack));
samples.emplace_back(createSample(timestamp + 1000, threadId2, callStack));
samples.emplace_back(createSample(timestamp + 2000, threadId1, callStack));
auto profile = createProfileWithSamples(std::move(samples));
auto tracingStartTime = HighResTimeStamp::now();
// Execute
serializer.serializeAndNotify(profile, tracingStartTime);
// [["Profile"], ["ProfileChunk", "ProfileChunk", "ProfileChunk]]
// Samples from different thread should never be grouped together in the same
// chunk.
ASSERT_EQ(notificationEvents_.size(), 2);
ASSERT_EQ(notificationEvents_[1].size(), 3);
}
TEST_F(
RuntimeSamplingProfileTraceEventSerializerTest,
TraceEventChunkSizeLimit) {
// Setup
auto notificationCallback = createNotificationCallback();
uint16_t traceEventChunkSize = 2;
uint16_t profileChunkSize = 2;
RuntimeSamplingProfileTraceEventSerializer serializer(
PerformanceTracer::getInstance(),
notificationCallback,
traceEventChunkSize,
profileChunkSize);
// Create multiple samples
std::vector<RuntimeSamplingProfile::SampleCallStackFrame> callStack = {
createJSCallFrame("foo", 1, "test.js", 10, 5)};
uint64_t timestamp = 1000000;
uint64_t threadId = 1;
std::vector<RuntimeSamplingProfile::Sample> samples;
samples.reserve(5);
for (int i = 0; i < 5; i++) {
samples.push_back(createSample(timestamp + i * 1000, threadId, callStack));
}
auto profile = createProfileWithSamples(std::move(samples));
auto tracingStartTime = HighResTimeStamp::now();
// Execute
serializer.serializeAndNotify(profile, tracingStartTime);
// [["Profile"], ["ProfileChunk", "ProfileChunk"], ["ProfileChunk"]]
ASSERT_EQ(notificationEvents_.size(), 3);
// Check that each chunk has at most traceEventChunkSize events
for (size_t i = 1; i < notificationEvents_.size(); i++) {
EXPECT_LE(notificationEvents_[i].size(), traceEventChunkSize);
}
}
TEST_F(RuntimeSamplingProfileTraceEventSerializerTest, ProfileChunkSizeLimit) {
// Setup
auto notificationCallback = createNotificationCallback();
// Set a small profile chunk size to test profile chunking
uint16_t traceEventChunkSize = 10;
uint16_t profileChunkSize = 2;
double samplesCount = 5;
RuntimeSamplingProfileTraceEventSerializer serializer(
PerformanceTracer::getInstance(),
notificationCallback,
traceEventChunkSize,
profileChunkSize);
// Create multiple samples
std::vector<RuntimeSamplingProfile::SampleCallStackFrame> callStack = {
createJSCallFrame("foo", 1, "test.js", 10, 5)};
uint64_t timestamp = 1000000;
uint64_t threadId = 1;
std::vector<RuntimeSamplingProfile::Sample> samples;
samples.reserve(samplesCount);
for (int i = 0; i < samplesCount; i++) {
samples.push_back(createSample(timestamp + i * 1000, threadId, callStack));
}
auto profile = createProfileWithSamples(std::move(samples));
auto tracingStartTime = HighResTimeStamp::now();
// Execute
serializer.serializeAndNotify(profile, tracingStartTime);
// [["Profile"], ["ProfileChunk", "ProfileChunk", "ProfileChunk"]]
ASSERT_EQ(notificationEvents_.size(), 2);
ASSERT_EQ(
notificationEvents_[1].size(),
std::ceil(samplesCount / profileChunkSize));
for (auto& profileChunk : notificationEvents_[1]) {
EXPECT_LE(
profileChunk["args"]["data"]["cpuProfile"]["samples"].size(),
profileChunkSize);
}
}
} // namespace facebook::react::jsinspector_modern::tracing
Выполнить команду
Для локальной разработки. Не используйте в интернете!