Files
ark_js_runtime/ecmascript/hprof/tests/hprof_test.cpp
T
wanyanglan 86cfe52253 add ark js_runtime
Signed-off-by: wanyanglan <wanyanglan1@huawei.com>
Change-Id: Iac7851492f10c0ef1303c621febb65e5fdd22e41
2021-09-05 16:05:06 +08:00

336 lines
10 KiB
C++

/*
* Copyright (c) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <cstdio>
#include <fstream>
#include "ecmascript/ecma_vm.h"
#include "ecmascript/global_env.h"
#include "ecmascript/hprof/heap_profiler.h"
#include "ecmascript/hprof/heap_profiler_interface.h"
#include "ecmascript/hprof/heap_snapshot.h"
#include "ecmascript/hprof/heap_snapshot_json_serializer.h"
#include "ecmascript/hprof/string_hashmap.h"
#include "ecmascript/js_thread.h"
#include "ecmascript/object_factory.h"
#include "ecmascript/tests/test_helper.h"
using namespace panda::ecmascript;
namespace panda::test {
class HProfTest : public testing::Test {
public:
static void SetUpTestCase()
{
GTEST_LOG_(INFO) << "SetUpTestCase";
}
static void TearDownTestCase()
{
GTEST_LOG_(INFO) << "TearDownCase";
}
void SetUp() override
{
TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
}
void TearDown() override
{
TestHelper::DestroyEcmaVMWithScope(instance, scope);
}
PandaVM *instance {nullptr};
EcmaHandleScope *scope {nullptr};
JSThread *thread {nullptr};
};
class HProfTestHelper {
public:
explicit HProfTestHelper(const CString &aFilePath) : filePath(aFilePath) {}
~HProfTestHelper() = default;
bool IsFileExist()
{
bool exist = false;
exist = SafeOpenFile();
SafeCloseFile();
return exist;
}
bool RemoveExistingFile()
{
int code = 0;
if (IsFileExist()) {
code = std::remove(filePath.c_str());
}
return code == 0 ? true : false;
}
bool GenerateHeapDump(JSThread *thread)
{
int retry = 2;
RemoveExistingFile();
HeapProfilerInterface::DumpHeapSnapShot(thread, DumpFormat::JSON, filePath);
while (!IsFileExist() && retry > 0) {
retry--;
HeapProfilerInterface::DumpHeapSnapShot(thread, DumpFormat::JSON, filePath);
}
return IsFileExist();
}
bool ContrastJSONLineHeader(int lineId, CString lineHeader)
{
bool allSame = false;
if (!SafeOpenFile()) { // No JSON File
allSame = false;
SafeCloseFile();
} else {
CString line;
int i = 1;
while (getline(inputFile, line)) {
if (i == lineId && line.find(lineHeader) != line.npos) {
allSame = true;
break;
}
i++;
}
SafeCloseFile();
}
return allSame;
}
bool ContrastJSONSectionPayload(CString dataLable, int fieldNum)
{
if (!SafeOpenFile()) { // No JSON File
SafeCloseFile();
return false;
} else {
CString line;
int i = 1;
while (getline(inputFile, line)) {
if (i > 10 && line.find(dataLable) != line.npos) { // 10 : Hit the line
CString::size_type pos = 0;
int loop = 0;
while ((pos = line.find(",", pos)) != line.npos) {
pos++;
loop++; // "," count
}
SafeCloseFile();
return loop == fieldNum - 1;
break;
}
i++; // Search the Next Line
}
SafeCloseFile();
}
return false; // Lost the Line
}
bool ContrastJSONClousure()
{
if (!SafeOpenFile()) { // No JSON File
SafeCloseFile();
return false;
}
CString lineBk; // The Last Line
CString line;
while (getline(inputFile, line)) {
lineBk = line;
}
SafeCloseFile();
return lineBk.compare("}") == 0;
}
int ExtractCountFromMeta(CString typeLable)
{
if (!SafeOpenFile()) { // No JSON File
SafeCloseFile();
return -1;
} else {
CString line;
int i = 1;
while (getline(inputFile, line)) {
int length = line.length() - typeLable.length() - 1;
if (line.find(typeLable) != line.npos) { // Get
if (line.find(",") == line.npos) { // "trace_function_count" end without ","
length = line.length() - typeLable.length();
}
line = line.substr(typeLable.length(), length);
SafeCloseFile();
return std::stoi(line.c_str());
}
i++;
}
SafeCloseFile();
}
return -1;
}
int ExtractCountFromPayload(CString dataLabel)
{
if (!SafeOpenFile()) { // No JSON File
SafeCloseFile();
return -1;
} else {
CString line;
bool hit = false;
int loop = 0;
while (getline(inputFile, line)) {
if (!hit && line.find(dataLabel) != line.npos) { // Get
loop += 1; // First Line
hit = true;
if (line.find("[]") != line.npos) { // Empty
loop = 0;
SafeCloseFile();
return loop;
} else {
continue;
}
}
if (hit) {
if (line.find("],") != line.npos) { // Reach End
loop += 1; // End Line
SafeCloseFile();
return loop;
} else {
loop++;
continue;
}
}
}
SafeCloseFile();
}
return -1;
}
private:
bool SafeOpenFile()
{
inputFile.clear();
inputFile.open(filePath.c_str(), std::ios::in);
int retry = 2;
while (!inputFile.good() && retry > 0) {
inputFile.open(filePath.c_str(), std::ios::in);
retry--;
}
return inputFile.good();
}
void SafeCloseFile()
{
inputFile.close();
inputFile.clear(); // Reset File status
}
CString filePath;
std::fstream inputFile {};
};
HWTEST_F_L0(HProfTest, GenerateFileForManualCheck)
{
HProfTestHelper tester("hprof_json_test.heapsnapshot");
ASSERT_TRUE(tester.GenerateHeapDump(thread));
}
HWTEST_F_L0(HProfTest, GenerateFile)
{
HProfTestHelper tester("GenerateFile.heapsnapshot");
ASSERT_TRUE(tester.GenerateHeapDump(thread));
ASSERT_TRUE(tester.RemoveExistingFile());
}
HWTEST_F_L0(HProfTest, ParseJSONHeader)
{
HProfTestHelper tester("ParseJSONHeader.heapsnapshot");
ASSERT_TRUE(tester.GenerateHeapDump(thread));
ASSERT_TRUE(tester.ContrastJSONLineHeader(1, "{\"snapshot\":"));
ASSERT_TRUE(tester.ContrastJSONLineHeader(2, "{\"meta\":"));
ASSERT_TRUE(tester.ContrastJSONLineHeader(3, "{\"node_fields\":"));
ASSERT_TRUE(tester.ContrastJSONLineHeader(4, "\"node_types\":"));
ASSERT_TRUE(tester.ContrastJSONLineHeader(5, "\"edge_fields\":"));
ASSERT_TRUE(tester.ContrastJSONLineHeader(6, "\"edge_types\":"));
ASSERT_TRUE(tester.ContrastJSONLineHeader(7, "\"trace_function_info_fields\":"));
ASSERT_TRUE(tester.ContrastJSONLineHeader(8, "\"trace_node_fields\":"));
ASSERT_TRUE(tester.ContrastJSONLineHeader(9, "\"sample_fields\":"));
ASSERT_TRUE(tester.ContrastJSONLineHeader(10, "\"location_fields\":"));
ASSERT_TRUE(tester.RemoveExistingFile());
}
HWTEST_F_L0(HProfTest, ContrastTraceFunctionInfo)
{
HProfTestHelper tester("ContrastTraceFunctionInfo.heapsnapshot");
ASSERT_TRUE(tester.GenerateHeapDump(thread));
ASSERT_TRUE(tester.ContrastJSONSectionPayload("\"trace_function_infos\":", 2)); // Empty
ASSERT_TRUE(tester.RemoveExistingFile());
}
HWTEST_F_L0(HProfTest, ContrastTraceTree)
{
HProfTestHelper tester("ContrastTraceTree.heapsnapshot");
ASSERT_TRUE(tester.GenerateHeapDump(thread));
ASSERT_TRUE(tester.ContrastJSONSectionPayload("\"trace_tree\":", 2)); // Empty
ASSERT_TRUE(tester.RemoveExistingFile());
}
HWTEST_F_L0(HProfTest, ContrastSamples)
{
HProfTestHelper tester("ContrastSamples.heapsnapshot");
ASSERT_TRUE(tester.GenerateHeapDump(thread));
ASSERT_TRUE(tester.ContrastJSONSectionPayload("\"samples\":", 2)); // Empty
ASSERT_TRUE(tester.RemoveExistingFile());
}
HWTEST_F_L0(HProfTest, ContrastLocations)
{
HProfTestHelper tester("ContrastLocations.heapsnapshot");
ASSERT_TRUE(tester.GenerateHeapDump(thread));
ASSERT_TRUE(tester.ContrastJSONSectionPayload("\"locations\":", 2)); // Empty
ASSERT_TRUE(tester.RemoveExistingFile());
}
HWTEST_F_L0(HProfTest, ContrastString)
{
HProfTestHelper tester("ContrastString.heapsnapshot");
ASSERT_TRUE(tester.GenerateHeapDump(thread));
ASSERT_TRUE(tester.ContrastJSONSectionPayload("\"strings\":[", 1 + 1));
ASSERT_TRUE(tester.RemoveExistingFile());
}
HWTEST_F_L0(HProfTest, ContrastClosure)
{
HProfTestHelper tester("ContrastClosure.heapsnapshot");
ASSERT_TRUE(tester.GenerateHeapDump(thread));
ASSERT_TRUE(tester.ContrastJSONClousure());
ASSERT_TRUE(tester.RemoveExistingFile());
}
HWTEST_F_L0(HProfTest, ContrastEdgeCount)
{
HProfTestHelper tester("ContrastEdgeCount.heapsnapshot");
ASSERT_TRUE(tester.GenerateHeapDump(thread));
ASSERT_TRUE(tester.ExtractCountFromMeta("\"edge_count\":") == tester.ExtractCountFromPayload("\"edges\":["));
ASSERT_TRUE(tester.RemoveExistingFile());
}
HWTEST_F_L0(HProfTest, ContrastTraceFunctionInfoCount)
{
HProfTestHelper tester("ContrastTraceFunctionInfoCount.heapsnapshot");
ASSERT_TRUE(tester.GenerateHeapDump(thread));
ASSERT_TRUE(tester.ExtractCountFromMeta("\"trace_function_count\":") ==
tester.ExtractCountFromPayload("\"trace_function_infos\":"));
ASSERT_TRUE(tester.RemoveExistingFile());
}
} // namespace panda::test