1/*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <gtest/gtest.h>
17
18#include "file_item_container.h"
19#include "pgo.h"
20
21namespace panda::panda_file::test {
22
23static void CreateItems(ItemContainer &container)
24{
25    // Add classes
26    ClassItem *empty_class_item = container.GetOrCreateClassItem("LTest;");
27    ClassItem *class_item_a = container.GetOrCreateClassItem("LAA;");
28    class_item_a->SetSuperClass(empty_class_item);
29
30    // Add method1
31    StringItem *method_name_1 = container.GetOrCreateStringItem("foo1");
32    PrimitiveTypeItem *ret_type_1 = container.GetOrCreatePrimitiveTypeItem(Type::TypeId::VOID);
33    std::vector<MethodParamItem> params_1;
34    ProtoItem *proto_item_1 = container.GetOrCreateProtoItem(ret_type_1, params_1);
35    MethodItem *method_item_1 = class_item_a->AddMethod(method_name_1, proto_item_1, ACC_PUBLIC | ACC_STATIC, params_1);
36
37    // Set code_1
38    std::vector<uint8_t> instructions_1 {1, 2, 3, 4};
39    CodeItem *code_item_1 = container.CreateItem<CodeItem>(0, 2, instructions_1);
40    method_item_1->SetCode(code_item_1);
41    code_item_1->AddMethod(method_item_1);
42}
43
44static void CreateProfile(std::string &filePath)
45{
46    filePath = "TestParseProfileData_test_data.txt";
47    std::ofstream test_file;
48    test_file.open(filePath);
49    test_file << "" << std::endl;
50    test_file << "string_item:test_field" << std::endl;
51    test_file << "class_item:AA" << std::endl;
52    test_file << "XXXXXXX" << std::endl;
53    test_file << "code_item:AA::foo1" << std::endl;
54    test_file << "code_item:Test::foo4" << std::endl;
55    test_file.close();
56}
57
58HWTEST(Pgo, MarkProfileItem, testing::ext::TestSize.Level0)
59{
60    ItemContainer container;
61    CreateItems(container);
62    panda::panda_file::pgo::ProfileOptimizer profile_opt;
63    for (auto &item : container.GetItems()) {
64        if (item->GetName() == CLASS_ITEM) {
65            profile_opt.MarkProfileItem(item, true);
66            EXPECT_EQ(item->GetPGORank(), panda::panda_file::PGO_CLASS_DEFAULT_COUNT + 1U);  // 1 means set pgo
67            profile_opt.MarkProfileItem(item, false);
68            EXPECT_EQ(item->GetPGORank(), panda::panda_file::PGO_CLASS_DEFAULT_COUNT);
69        } else if (item->GetName() == STRING_ITEM) {
70            profile_opt.MarkProfileItem(item, true);
71            EXPECT_EQ(item->GetPGORank(), panda::panda_file::PGO_STRING_DEFAULT_COUNT + 1U);  // 1 means set pgo
72            profile_opt.MarkProfileItem(item, false);
73            EXPECT_EQ(item->GetPGORank(), panda::panda_file::PGO_STRING_DEFAULT_COUNT);
74        } else if (item->GetName() == CODE_ITEM) {
75            profile_opt.MarkProfileItem(item, true);
76            EXPECT_EQ(item->GetPGORank(), panda::panda_file::PGO_CODE_DEFAULT_COUNT + 1U);  // 1 means set pgo
77            profile_opt.MarkProfileItem(item, false);
78            EXPECT_EQ(item->GetPGORank(), panda::panda_file::PGO_CODE_DEFAULT_COUNT);
79        }
80    }
81}
82
83HWTEST(Pgo, ParseProfileData0, testing::ext::TestSize.Level0)
84{
85    panda::panda_file::pgo::ProfileOptimizer profile_opt;
86    EXPECT_FALSE(profile_opt.ParseProfileData());
87}
88
89HWTEST(Pgo, ParseProfileData1, testing::ext::TestSize.Level0)
90{
91    std::string profile_path;
92    CreateProfile(profile_path);
93
94    panda::panda_file::pgo::ProfileOptimizer profile_opt;
95    profile_opt.SetProfilePath(profile_path);
96    EXPECT_TRUE(profile_opt.ParseProfileData());
97}
98
99HWTEST(Pgo, ProfileGuidedRelayout, testing::ext::TestSize.Level0)
100{
101    ItemContainer container;
102    CreateItems(container);
103
104    std::string profile_path;
105    CreateProfile(profile_path);
106
107    panda::panda_file::pgo::ProfileOptimizer profile_opt;
108    for (auto &item : container.GetItems()) {
109        item->SetNeedsEmit(false);
110    }
111    profile_opt.ProfileGuidedRelayout(container.GetItems());
112    for (auto &item : container.GetItems()) {
113        item->SetNeedsEmit(true);
114    }
115    profile_opt.ProfileGuidedRelayout(container.GetItems());
116    for (auto &item : container.GetItems()) {
117        if (item->GetName() == CLASS_ITEM) {
118            EXPECT_EQ(item->GetPGORank(), panda::panda_file::PGO_CLASS_DEFAULT_COUNT);
119        }
120    }
121}
122
123}  // namespace panda::panda_file::test
124