148f512ceSopenharmony_ci/*
248f512ceSopenharmony_ci * Copyright (c) 2021 Huawei Device Co., Ltd.
348f512ceSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
448f512ceSopenharmony_ci * you may not use this file except in compliance with the License.
548f512ceSopenharmony_ci * You may obtain a copy of the License at
648f512ceSopenharmony_ci *
748f512ceSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
848f512ceSopenharmony_ci *
948f512ceSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1048f512ceSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1148f512ceSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1248f512ceSopenharmony_ci * See the License for the specific language governing permissions and
1348f512ceSopenharmony_ci * limitations under the License.
1448f512ceSopenharmony_ci */
1548f512ceSopenharmony_ci
1648f512ceSopenharmony_ci#include "perf_events_test.h"
1748f512ceSopenharmony_ci
1848f512ceSopenharmony_ci#include <chrono>
1948f512ceSopenharmony_ci#include <cinttypes>
2048f512ceSopenharmony_ci#include <cstdlib>
2148f512ceSopenharmony_ci#include <thread>
2248f512ceSopenharmony_ci#include <unistd.h>
2348f512ceSopenharmony_ci
2448f512ceSopenharmony_ci#include "debug_logger.h"
2548f512ceSopenharmony_ci#include "utilities.h"
2648f512ceSopenharmony_ci
2748f512ceSopenharmony_ciusing namespace testing::ext;
2848f512ceSopenharmony_ciusing namespace std;
2948f512ceSopenharmony_ciusing namespace OHOS::HiviewDFX;
3048f512ceSopenharmony_ci
3148f512ceSopenharmony_cinamespace OHOS {
3248f512ceSopenharmony_cinamespace Developtools {
3348f512ceSopenharmony_cinamespace HiPerf {
3448f512ceSopenharmony_ciclass PerfEventsTest : public testing::Test {
3548f512ceSopenharmony_cipublic:
3648f512ceSopenharmony_ci    static void SetUpTestCase(void);
3748f512ceSopenharmony_ci    static void TearDownTestCase(void);
3848f512ceSopenharmony_ci    void SetUp();
3948f512ceSopenharmony_ci    void TearDown();
4048f512ceSopenharmony_ci
4148f512ceSopenharmony_ci    static void TestCodeThread(void);
4248f512ceSopenharmony_ci    static void RunTestThreads(std::vector<std::thread> &threads);
4348f512ceSopenharmony_ci    static void SetAllConfig(PerfEvents &event);
4448f512ceSopenharmony_ci    static bool RecordCount(std::unique_ptr<PerfEventRecord> record);
4548f512ceSopenharmony_ci    static void StatCount(
4648f512ceSopenharmony_ci        const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents);
4748f512ceSopenharmony_ci
4848f512ceSopenharmony_ci    static constexpr int TEST_CODE_MEM_FILE_SIZE = 1024;
4948f512ceSopenharmony_ci    static constexpr auto TEST_CODE_SLEEP_BEFORE_RUN = 500ms;
5048f512ceSopenharmony_ci    static constexpr auto TEST_CODE_SLEEP_AFTER_RUN = 1000ms;
5148f512ceSopenharmony_ci    static constexpr int TEST_CODE_RUN_TIME = 10240;
5248f512ceSopenharmony_ci    static constexpr int DOUBLE = 2;
5348f512ceSopenharmony_ci    static constexpr int TRIPLE = 3;
5448f512ceSopenharmony_ci    static constexpr auto TEST_TIME = 3s;
5548f512ceSopenharmony_ci    static constexpr auto DEFAULT_TRACKING_TIME = 1000;
5648f512ceSopenharmony_ci    static constexpr auto DEFAULT_STAT_REPORT_TIME = 500;
5748f512ceSopenharmony_ci    static constexpr auto DEFAULT_SAMPLE_MMAPAGE = 256;
5848f512ceSopenharmony_ci
5948f512ceSopenharmony_ci    static uint64_t g_recordCount;
6048f512ceSopenharmony_ci    static uint64_t g_statCount;
6148f512ceSopenharmony_ci};
6248f512ceSopenharmony_ci
6348f512ceSopenharmony_civoid PerfEventsTest::SetUpTestCase() {}
6448f512ceSopenharmony_ci
6548f512ceSopenharmony_civoid PerfEventsTest::TearDownTestCase() {}
6648f512ceSopenharmony_ci
6748f512ceSopenharmony_civoid PerfEventsTest::SetUp() {}
6848f512ceSopenharmony_ci
6948f512ceSopenharmony_civoid PerfEventsTest::TearDown() {}
7048f512ceSopenharmony_ci
7148f512ceSopenharmony_ciuint64_t PerfEventsTest::g_recordCount = 0;
7248f512ceSopenharmony_ciuint64_t PerfEventsTest::g_statCount = 0;
7348f512ceSopenharmony_ci
7448f512ceSopenharmony_cibool PerfEventsTest::RecordCount(std::unique_ptr<PerfEventRecord> record)
7548f512ceSopenharmony_ci{
7648f512ceSopenharmony_ci    g_recordCount++;
7748f512ceSopenharmony_ci    if (record->GetType() == PERF_RECORD_SAMPLE) {
7848f512ceSopenharmony_ci        // the record is allowed from a cache memory, does not free memory after use
7948f512ceSopenharmony_ci        record.release();
8048f512ceSopenharmony_ci    }
8148f512ceSopenharmony_ci    return true;
8248f512ceSopenharmony_ci}
8348f512ceSopenharmony_ci
8448f512ceSopenharmony_civoid PerfEventsTest::StatCount(
8548f512ceSopenharmony_ci    const std::map<std::string, std::unique_ptr<PerfEvents::CountEvent>> &countEvents)
8648f512ceSopenharmony_ci{
8748f512ceSopenharmony_ci    g_statCount++;
8848f512ceSopenharmony_ci}
8948f512ceSopenharmony_ci
9048f512ceSopenharmony_civoid PerfEventsTest::TestCodeThread()
9148f512ceSopenharmony_ci{
9248f512ceSopenharmony_ci    std::vector<std::unique_ptr<char[]>> mems;
9348f512ceSopenharmony_ci    int tid = gettid();
9448f512ceSopenharmony_ci    printf("%s:%d ++\n", __FUNCTION__, tid);
9548f512ceSopenharmony_ci    for (int n = 0; n < TRIPLE; n++) {
9648f512ceSopenharmony_ci        std::this_thread::sleep_for(TEST_CODE_SLEEP_BEFORE_RUN);
9748f512ceSopenharmony_ci        constexpr size_t memSize {TEST_CODE_MEM_FILE_SIZE};
9848f512ceSopenharmony_ci        for (int i = 0; i < TEST_CODE_RUN_TIME; i++) {
9948f512ceSopenharmony_ci            if (i % DOUBLE == 0) {
10048f512ceSopenharmony_ci                mems.push_back(std::make_unique<char[]>(memSize));
10148f512ceSopenharmony_ci            } else {
10248f512ceSopenharmony_ci                mems.push_back(std::make_unique<char[]>(memSize * DOUBLE));
10348f512ceSopenharmony_ci            }
10448f512ceSopenharmony_ci        }
10548f512ceSopenharmony_ci
10648f512ceSopenharmony_ci        for (int i = 0; i < TEST_CODE_RUN_TIME; i++) {
10748f512ceSopenharmony_ci            mems.pop_back();
10848f512ceSopenharmony_ci        }
10948f512ceSopenharmony_ci
11048f512ceSopenharmony_ci        std::this_thread::sleep_for(TEST_CODE_SLEEP_AFTER_RUN);
11148f512ceSopenharmony_ci    }
11248f512ceSopenharmony_ci    printf("%s:%d --\n", __FUNCTION__, tid);
11348f512ceSopenharmony_ci}
11448f512ceSopenharmony_ci
11548f512ceSopenharmony_civoid PerfEventsTest::RunTestThreads(std::vector<std::thread> &threads)
11648f512ceSopenharmony_ci{
11748f512ceSopenharmony_ci    for (long i = 0; i < sysconf(_SC_NPROCESSORS_CONF); i++) {
11848f512ceSopenharmony_ci        threads.emplace_back(std::thread(&TestCodeThread));
11948f512ceSopenharmony_ci    }
12048f512ceSopenharmony_ci}
12148f512ceSopenharmony_ci
12248f512ceSopenharmony_ci// it isn't include sample and stat
12348f512ceSopenharmony_civoid PerfEventsTest::SetAllConfig(PerfEvents &event)
12448f512ceSopenharmony_ci{
12548f512ceSopenharmony_ci    std::vector<pid_t> selectCpus_;
12648f512ceSopenharmony_ci    event.SetCpu(selectCpus_);
12748f512ceSopenharmony_ci    std::vector<pid_t> pids;
12848f512ceSopenharmony_ci    event.SetPid(pids);
12948f512ceSopenharmony_ci    event.SetSystemTarget(true);
13048f512ceSopenharmony_ci    event.SetTimeOut(DEFAULT_TRACKING_TIME);
13148f512ceSopenharmony_ci    event.SetInherit(false);
13248f512ceSopenharmony_ci    std::vector<std::string> trackedCommand_ {"ls"};
13348f512ceSopenharmony_ci    event.SetTrackedCommand(trackedCommand_);
13448f512ceSopenharmony_ci    const unsigned int frequency = 1000;
13548f512ceSopenharmony_ci    event.SetSampleFrequency(frequency);
13648f512ceSopenharmony_ci    const uint32_t dwarfSampleStackSize = 64;
13748f512ceSopenharmony_ci    event.SetDwarfSampleStackSize(dwarfSampleStackSize);
13848f512ceSopenharmony_ci    const int clockId = 1;
13948f512ceSopenharmony_ci    event.SetClockId(clockId);
14048f512ceSopenharmony_ci
14148f512ceSopenharmony_ci    // addevent must be tail
14248f512ceSopenharmony_ci    event.AddDefaultEvent(PERF_TYPE_HARDWARE);
14348f512ceSopenharmony_ci    event.AddDefaultEvent(PERF_TYPE_SOFTWARE);
14448f512ceSopenharmony_ci}
14548f512ceSopenharmony_ci
14648f512ceSopenharmony_cistatic void RunTrack(PerfEvents &event)
14748f512ceSopenharmony_ci{
14848f512ceSopenharmony_ci    ASSERT_EQ(event.StartTracking(), true);
14948f512ceSopenharmony_ci}
15048f512ceSopenharmony_ci
15148f512ceSopenharmony_ci/**
15248f512ceSopenharmony_ci * @tc.name: Test
15348f512ceSopenharmony_ci * @tc.desc:
15448f512ceSopenharmony_ci * @tc.type: FUNC
15548f512ceSopenharmony_ci */
15648f512ceSopenharmony_ciHWTEST_F(PerfEventsTest, GetSupportEvents, TestSize.Level1)
15748f512ceSopenharmony_ci{
15848f512ceSopenharmony_ci    ScopeDebugLevel tempLogLevel(LEVEL_DEBUG);
15948f512ceSopenharmony_ci    StdoutRecord stdoutRecord;
16048f512ceSopenharmony_ci    stdoutRecord.Start();
16148f512ceSopenharmony_ci
16248f512ceSopenharmony_ci    PerfEvents event;
16348f512ceSopenharmony_ci    perf_type_id id = PERF_TYPE_HARDWARE;
16448f512ceSopenharmony_ci    while (id < PERF_TYPE_MAX) {
16548f512ceSopenharmony_ci        std::map<__u64, std::string> supportEvent = event.GetSupportEvents(id);
16648f512ceSopenharmony_ci        for (auto it = supportEvent.begin(); it != supportEvent.end(); ++it) {
16748f512ceSopenharmony_ci            printf("[%lld]\t%s\n", it->first, it->second.c_str());
16848f512ceSopenharmony_ci        }
16948f512ceSopenharmony_ci        id = perf_type_id(id + 1);
17048f512ceSopenharmony_ci    }
17148f512ceSopenharmony_ci
17248f512ceSopenharmony_ci    std::string stringOut = stdoutRecord.Stop();
17348f512ceSopenharmony_ci}
17448f512ceSopenharmony_ci
17548f512ceSopenharmony_ciHWTEST_F(PerfEventsTest, GetTypeName, TestSize.Level1)
17648f512ceSopenharmony_ci{
17748f512ceSopenharmony_ci    ScopeDebugLevel tempLogLevel(LEVEL_DEBUG);
17848f512ceSopenharmony_ci    StdoutRecord stdoutRecord;
17948f512ceSopenharmony_ci    stdoutRecord.Start();
18048f512ceSopenharmony_ci
18148f512ceSopenharmony_ci    PerfEvents event;
18248f512ceSopenharmony_ci    perf_type_id id = PERF_TYPE_HARDWARE;
18348f512ceSopenharmony_ci    while (id < PERF_TYPE_MAX) {
18448f512ceSopenharmony_ci        std::string typeName = event.GetTypeName(id);
18548f512ceSopenharmony_ci        EXPECT_GT(typeName.size(), 0u) << "the type should have name";
18648f512ceSopenharmony_ci        printf("type[%d]\tname : %s\n", id, typeName.c_str());
18748f512ceSopenharmony_ci        id = perf_type_id(id + 1);
18848f512ceSopenharmony_ci    }
18948f512ceSopenharmony_ci
19048f512ceSopenharmony_ci    std::string stringOut = stdoutRecord.Stop();
19148f512ceSopenharmony_ci}
19248f512ceSopenharmony_ci
19348f512ceSopenharmony_ciHWTEST_F(PerfEventsTest, RecordNormal, TestSize.Level1)
19448f512ceSopenharmony_ci{
19548f512ceSopenharmony_ci    ScopeDebugLevel tempLogLevel(LEVEL_DEBUG);
19648f512ceSopenharmony_ci    StdoutRecord stdoutRecord;
19748f512ceSopenharmony_ci    stdoutRecord.Start();
19848f512ceSopenharmony_ci
19948f512ceSopenharmony_ci    PerfEvents event;
20048f512ceSopenharmony_ci    // prepare
20148f512ceSopenharmony_ci    g_recordCount = 0;
20248f512ceSopenharmony_ci    event.SetMmapPages(DEFAULT_SAMPLE_MMAPAGE);
20348f512ceSopenharmony_ci    event.SetRecordCallBack(RecordCount);
20448f512ceSopenharmony_ci
20548f512ceSopenharmony_ci    std::vector<pid_t> selectCpus_;
20648f512ceSopenharmony_ci    event.SetCpu(selectCpus_);
20748f512ceSopenharmony_ci    std::vector<pid_t> pids;
20848f512ceSopenharmony_ci    event.SetPid(pids);
20948f512ceSopenharmony_ci    const unsigned int frequency = 1000;
21048f512ceSopenharmony_ci    event.SetSampleFrequency(frequency);
21148f512ceSopenharmony_ci    event.SetSystemTarget(true);
21248f512ceSopenharmony_ci    event.SetTimeOut(DEFAULT_TRACKING_TIME);
21348f512ceSopenharmony_ci    event.SetInherit(false);
21448f512ceSopenharmony_ci    std::vector<std::string> trackedCommand_ {"ls"};
21548f512ceSopenharmony_ci    event.SetTrackedCommand(trackedCommand_);
21648f512ceSopenharmony_ci    event.AddDefaultEvent(PERF_TYPE_SOFTWARE);
21748f512ceSopenharmony_ci    event.AddDefaultEvent(PERF_TYPE_HARDWARE);
21848f512ceSopenharmony_ci
21948f512ceSopenharmony_ci    ASSERT_EQ(event.PrepareTracking(), true);
22048f512ceSopenharmony_ci    std::thread runThread(RunTrack, std::ref(event));
22148f512ceSopenharmony_ci    std::vector<std::thread> testThreads;
22248f512ceSopenharmony_ci    RunTestThreads(testThreads);
22348f512ceSopenharmony_ci
22448f512ceSopenharmony_ci    std::this_thread::sleep_for(TEST_TIME);
22548f512ceSopenharmony_ci    EXPECT_EQ(event.PauseTracking(), true);
22648f512ceSopenharmony_ci    std::this_thread::sleep_for(TEST_TIME); // wait for clearing mmap buffer
22748f512ceSopenharmony_ci    uint64_t recordCount = g_recordCount;
22848f512ceSopenharmony_ci    std::this_thread::sleep_for(TEST_TIME);
22948f512ceSopenharmony_ci    EXPECT_EQ(recordCount, g_recordCount) << "now should have no record";
23048f512ceSopenharmony_ci    EXPECT_EQ(event.ResumeTracking(), true);
23148f512ceSopenharmony_ci    TestCodeThread();
23248f512ceSopenharmony_ci    std::this_thread::sleep_for(TEST_TIME);
23348f512ceSopenharmony_ci    EXPECT_EQ(event.StopTracking(), true);
23448f512ceSopenharmony_ci    runThread.join();
23548f512ceSopenharmony_ci    for (std::thread &t : testThreads) {
23648f512ceSopenharmony_ci        t.join();
23748f512ceSopenharmony_ci    }
23848f512ceSopenharmony_ci    ASSERT_GT(g_recordCount, recordCount) << "should have more records";
23948f512ceSopenharmony_ci
24048f512ceSopenharmony_ci    size_t lostSamples = 0;
24148f512ceSopenharmony_ci    size_t lostNonSamples = 0;
24248f512ceSopenharmony_ci    event.GetLostSamples(lostSamples, lostNonSamples);
24348f512ceSopenharmony_ci
24448f512ceSopenharmony_ci    std::string stringOut = stdoutRecord.Stop();
24548f512ceSopenharmony_ci}
24648f512ceSopenharmony_ci
24748f512ceSopenharmony_ciHWTEST_F(PerfEventsTest, RecordSetAll, TestSize.Level1)
24848f512ceSopenharmony_ci{
24948f512ceSopenharmony_ci    ScopeDebugLevel tempLogLevel(LEVEL_DEBUG);
25048f512ceSopenharmony_ci    StdoutRecord stdoutRecord;
25148f512ceSopenharmony_ci    stdoutRecord.Start();
25248f512ceSopenharmony_ci
25348f512ceSopenharmony_ci    PerfEvents event;
25448f512ceSopenharmony_ci    // prepare
25548f512ceSopenharmony_ci    g_recordCount = 0;
25648f512ceSopenharmony_ci    event.SetMmapPages(DEFAULT_SAMPLE_MMAPAGE);
25748f512ceSopenharmony_ci    event.SetRecordCallBack(RecordCount);
25848f512ceSopenharmony_ci    SetAllConfig(event);
25948f512ceSopenharmony_ci    ASSERT_EQ(event.PrepareTracking(), true);
26048f512ceSopenharmony_ci    std::thread runThread(RunTrack, std::ref(event));
26148f512ceSopenharmony_ci    std::vector<std::thread> testThreads;
26248f512ceSopenharmony_ci    RunTestThreads(testThreads);
26348f512ceSopenharmony_ci
26448f512ceSopenharmony_ci    std::this_thread::sleep_for(TEST_TIME);
26548f512ceSopenharmony_ci    EXPECT_EQ(event.PauseTracking(), true);
26648f512ceSopenharmony_ci    std::this_thread::sleep_for(TEST_TIME); // wait for clearing mmap buffer
26748f512ceSopenharmony_ci    uint64_t recordCount = g_recordCount;
26848f512ceSopenharmony_ci    std::this_thread::sleep_for(TEST_TIME);
26948f512ceSopenharmony_ci    EXPECT_EQ(recordCount, g_recordCount) << "now should have no record";
27048f512ceSopenharmony_ci    EXPECT_EQ(event.ResumeTracking(), true);
27148f512ceSopenharmony_ci    TestCodeThread();
27248f512ceSopenharmony_ci    std::this_thread::sleep_for(TEST_TIME);
27348f512ceSopenharmony_ci    EXPECT_EQ(event.StopTracking(), true);
27448f512ceSopenharmony_ci    runThread.join();
27548f512ceSopenharmony_ci    for (std::thread &t : testThreads) {
27648f512ceSopenharmony_ci        t.join();
27748f512ceSopenharmony_ci    }
27848f512ceSopenharmony_ci    ASSERT_GT(g_recordCount, recordCount) << "should have more records";
27948f512ceSopenharmony_ci
28048f512ceSopenharmony_ci    std::string stringOut = stdoutRecord.Stop();
28148f512ceSopenharmony_ci}
28248f512ceSopenharmony_ci
28348f512ceSopenharmony_ciHWTEST_F(PerfEventsTest, StatNormal, TestSize.Level1)
28448f512ceSopenharmony_ci{
28548f512ceSopenharmony_ci    ScopeDebugLevel tempLogLevel(LEVEL_DEBUG);
28648f512ceSopenharmony_ci    StdoutRecord stdoutRecord;
28748f512ceSopenharmony_ci    stdoutRecord.Start();
28848f512ceSopenharmony_ci
28948f512ceSopenharmony_ci    PerfEvents event;
29048f512ceSopenharmony_ci    // prepare
29148f512ceSopenharmony_ci    g_statCount = 0;
29248f512ceSopenharmony_ci    std::vector<pid_t> selectCpus_;
29348f512ceSopenharmony_ci    event.SetCpu(selectCpus_);
29448f512ceSopenharmony_ci    std::vector<pid_t> pids;
29548f512ceSopenharmony_ci    event.SetPid(pids);
29648f512ceSopenharmony_ci    event.SetSystemTarget(true);
29748f512ceSopenharmony_ci    event.SetTimeOut(DEFAULT_TRACKING_TIME);
29848f512ceSopenharmony_ci    event.SetTimeReport(DEFAULT_STAT_REPORT_TIME);
29948f512ceSopenharmony_ci    event.SetVerboseReport(false);
30048f512ceSopenharmony_ci    event.SetInherit(false);
30148f512ceSopenharmony_ci    std::vector<std::string> trackedCommand_ {"ls"};
30248f512ceSopenharmony_ci    event.SetTrackedCommand(trackedCommand_);
30348f512ceSopenharmony_ci    event.AddDefaultEvent(PERF_TYPE_SOFTWARE);
30448f512ceSopenharmony_ci    event.AddDefaultEvent(PERF_TYPE_TRACEPOINT);
30548f512ceSopenharmony_ci    event.SetStatCallBack(StatCount);
30648f512ceSopenharmony_ci    ASSERT_EQ(event.PrepareTracking(), true);
30748f512ceSopenharmony_ci    std::thread runThread(RunTrack, std::ref(event));
30848f512ceSopenharmony_ci    std::vector<std::thread> testThreads;
30948f512ceSopenharmony_ci    RunTestThreads(testThreads);
31048f512ceSopenharmony_ci
31148f512ceSopenharmony_ci    std::this_thread::sleep_for(TEST_TIME);
31248f512ceSopenharmony_ci    EXPECT_EQ(event.PauseTracking(), true);
31348f512ceSopenharmony_ci    EXPECT_GT(g_statCount, 0u) << "should have stats";
31448f512ceSopenharmony_ci    uint64_t statCount = g_statCount;
31548f512ceSopenharmony_ci    std::this_thread::sleep_for(TEST_TIME);
31648f512ceSopenharmony_ci    EXPECT_EQ(event.ResumeTracking(), true);
31748f512ceSopenharmony_ci    std::this_thread::sleep_for(TEST_TIME);
31848f512ceSopenharmony_ci    EXPECT_EQ(event.StopTracking(), true);
31948f512ceSopenharmony_ci    runThread.join();
32048f512ceSopenharmony_ci    for (std::thread &t : testThreads) {
32148f512ceSopenharmony_ci        t.join();
32248f512ceSopenharmony_ci    }
32348f512ceSopenharmony_ci    EXPECT_GT(g_statCount, statCount) << "should have more stats";
32448f512ceSopenharmony_ci
32548f512ceSopenharmony_ci    std::string stringOut = stdoutRecord.Stop();
32648f512ceSopenharmony_ci}
32748f512ceSopenharmony_ci} // namespace HiPerf
32848f512ceSopenharmony_ci} // namespace Developtools
32948f512ceSopenharmony_ci} // namespace OHOS
330